home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / jpl_c.zip / FTOA.C < prev    next >
Text File  |  1986-05-18  |  6KB  |  233 lines

  1. /* 1.3  10-08-85                        (ftoa.c)
  2.  ************************************************************************
  3.  *            Robert C. Tausworthe                *
  4.  *            Jet Propulsion Laboratory            *
  5.  *            Pasadena, CA 91009        1985        *
  6.  ************************************************************************/
  7.  
  8. #include "defs.h"
  9. #include "ctype.h"
  10. #include "stdtyp.h"
  11. #include "mathcons.h"
  12.  
  13. /************************************************************************/
  14.     STRING
  15. ftoa(s, x, pr, mode)    /* Convert x to ascii string s with precision pr
  16.                in mode 'e', 'f', or 'g' format.
  17.                Return pointer to s.                */
  18. /*----------------------------------------------------------------------*/
  19. STRING s;
  20. double x;
  21. {
  22.     BOOL minus;
  23.     STRING p, astoi();
  24.     int d;
  25.     double normalize();
  26.  
  27.     p = s;        /* save string pointer for returns    */
  28.     *s = NULL;
  29.     if (pr > DPRECISION)
  30.         pr = DPRECISION;
  31.     if (minus = ((x < 0.0) ? TRUE : FALSE)) /* work with pos. numbers */
  32.         x = -x;
  33.     x = normalize(x, &d);
  34.     *s++ = (minus ? '-' : ' ');    /* put sign into string    */
  35.     switch (tolower(mode))
  36.     {    case 'e':
  37.         case 0:
  38.             expform(s, x, d, pr);
  39.             break;
  40.         case 'f':
  41.         case 1:
  42.             floatform(s, x, d, pr);
  43.             break;
  44.         case 'g':
  45.         case 2:
  46.             minform(s, x, d, pr);
  47.             break;
  48.         default:
  49.             ;
  50.     }
  51.     return p;
  52. }
  53.  
  54. /*\p*********************************************************************/
  55.     LOCAL double
  56. normalize(x, d)        /* return x * 10^-d in [1, 10), with d set so
  57.                this condition is met.            */
  58. /*----------------------------------------------------------------------*/
  59. double x;
  60. int *d;
  61. {
  62.     /****************************************************************
  63.      * This array contains 2^n powers of 10 up to n = BIG10X-1    *
  64.      ****************************************************************/
  65.  
  66.     LOCAL double tentothe2tothe[BIG10X] =
  67.     {    10., 100., 10000., 100000000., 10000000000000000.,
  68.         100000000000000000000000000000000.
  69. #ifdef AZTEC
  70.         , 1.0e64, 1.0e128
  71. #endif
  72.  
  73. #ifdef SUN
  74.         , 1.0e64, 1.0e128, 1.0e256
  75. #endif
  76.     };
  77.  
  78.     /********************************************************
  79.      * Also, make this array be 2^n up to 2^(BIG10X-1)    *
  80.      ********************************************************/
  81.  
  82.     LOCAL int twoto[BIG10X] =
  83.     {    1, 2, 4, 8, 16, 32
  84. #ifdef AZTEC
  85.         , 64, 128
  86. #endif
  87.  
  88. #ifdef SUN
  89.         , 64, 128, 256
  90. #endif
  91.     };
  92.  
  93.     int i;
  94.  
  95.     *d = 0;
  96.     if (x ISNT 0.0)
  97.         if (x < 1.0)
  98.         {    for (i = 1; x < SYMLEAST; i++)
  99.                 x *= 10.0;    
  100.             x = 10.0 / normalize(1.0 / x, d);
  101.             *d = -*d - i;
  102.             if (x >= 10.0)    /* compensate if on the edge.    */
  103.             {    x /= 10.0;
  104.                 ++*d;
  105.             }
  106.         }    
  107.         else
  108.             for (i = BIG10X; x >= 10.0 AND --i >= 0; )
  109.                 if (x >= tentothe2tothe[i])
  110.                 {    x /= tentothe2tothe[i];
  111.                     *d += twoto[i];
  112.                 }
  113.     return x;
  114. }    
  115.  
  116. /*\p*********************************************************************/
  117.     LOCAL VOID
  118. floatform(s, x, d, pr)    /* put x * 10^d (precision pr) into string s
  119.                in f-format.                    */
  120. /*----------------------------------------------------------------------*/
  121. STRING s;
  122. double x;
  123. {
  124.     double roundoff();
  125.     int i;
  126.  
  127.     x = roundoff(x, &d, pr + ((d > 0) ? d : 0));
  128.     if (d < 0)
  129.         *s++ = '0';
  130.     else
  131.         while (d >= 0)
  132.         {    *s++ = pickdigit(&x);
  133.             d--;
  134.         }
  135.     if ((i = pr) >= 0)
  136.         *s++ = '.';
  137.     while (++d < 0 AND i-- > 0)
  138.         *s++ = '0';
  139.     while (i-- > 0)
  140.         *s++ = pickdigit(&x);
  141.     *s = NULL;
  142. }
  143.  
  144. /************************************************************************/
  145.     LOCAL VOID
  146. expform(s, x, d, pr)    /* put x * 10^d (precision pr) into string s
  147.                in e-format                    */
  148. /*----------------------------------------------------------------------*/
  149. STRING s;
  150. double x;
  151. {
  152.     double roundoff();
  153.     int i;
  154.  
  155.     x = roundoff(x, &d, i = pr);
  156.     *s++ = pickdigit(&x);
  157.     *s++ = '.';
  158.     while (i-- > 0)
  159.         *s++ = pickdigit(&x);
  160.     *s++ = 'e';
  161.     itoa(s, d, 0);    /* minimum width */
  162. }
  163.  
  164. /*\p*********************************************************************/
  165.     LOCAL VOID
  166. minform(s, x, d, pr)    /* put x * 10^d into string s in minimum format
  167.                with precision pr                */
  168. /*----------------------------------------------------------------------*/
  169. STRING s;
  170. double x;
  171. {
  172.     int i, j;
  173.  
  174.     if (d < 5)
  175.     {    floatform(s, x, d, pr);
  176.         i = strlen(s) - 1;
  177.         while (s[i] IS '0')
  178.             s[i--] = NULL;
  179.         if (s[i] IS '.')
  180.             s[i--] = NULL;
  181.     }
  182.     else
  183.     {    expform(s, x, d, pr);
  184.         j = strlen(s) - 1;
  185.         while (s[j] ISNT 'e')
  186.             j--;
  187.         for (i = j - 1; s[i] IS '0'; i--)
  188.             ;
  189.         strcpy(&s[++i], &s[j]);
  190.     }
  191. }
  192.  
  193. /************************************************************************/
  194.     LOCAL
  195. pickdigit(x)    /* return ascii leading digit of x, strip it off, and
  196.            prepare x for extraction of next digit.        */
  197. /*----------------------------------------------------------------------*/
  198. double *x;
  199. {
  200.     int n;
  201.  
  202.     n = *x;            /* take integer part.            */
  203.     *x = 10 * ( *x - n);    /* strip it off, and renormalize x    */
  204.     return (n + '0');
  205. }
  206. /*\p*********************************************************************/
  207.     LOCAL double
  208. roundoff(x, d, p)    /* return x * 10^*d rounded to precision p    */
  209.  
  210. /*----------------------------------------------------------------------*/
  211. double x;
  212. int *d;
  213. {                   /*************************************/
  214.     LOCAL double rounder[21] = /* NOTE: DPRECISION must be no larger*/
  215.                    /* than the number of elements in    */
  216.                    /* this array.            */
  217.                    /*************************************/
  218.     {    0.5,     0.5e-1,  0.5e-2,  0.5e-3,  0.5e-4,  0.5e-5,
  219.         0.5e-6,  0.5e-7,  0.5e-8,  0.5e-9,  0.5e-10, 0.5e-11,
  220.         0.5e-12, 0.5e-13, 0.5e-14, 0.5e-15, 0.5e-16, 0.5e-17,
  221.         0.5e-18, 0.5e-19, 0.5e-20
  222.     };
  223.     double y;
  224.  
  225.     if ((y = x) ISNT 0.0)
  226.         if (p <= DPRECISION)
  227.             if ((x += rounder[p]) >= 10.0)
  228.             {    x = y / 10.0 + rounder[p];
  229.                 ++*d;
  230.             }
  231.     return x;
  232. }
  233.